﻿using System;
using System.Collections.Generic;
using MinhUtils;
using System.Data.SQLite;
using System.Threading;
using MangaGrr.DomainModel;

namespace MangaGrr
{
    class MGRDataAccessor
    {
        private static readonly string CONNECTION_STRING = @"Data Source=mgrDb.db;Version=3;New=False;Compress=True;";
        private static SQLiteConnection _connection;
        private static List<MangaSite> _mangaSiteList = null;

        private static volatile int _connectionCount = 0;
        private static readonly Mutex _mutex = new Mutex();

        private static void ConnectToDatabase()
        {
            _mutex.WaitOne();
            //increase connection count
            _connectionCount++;

            //if connection count is 1 (1st connection) then create new connection
            if (_connectionCount == 1)
            {
                _connection = new SQLiteConnection(CONNECTION_STRING);
                _connection.Open();
            }
            _mutex.ReleaseMutex();
        }

        private static void DisconnectFromDatabase()
        {
            _mutex.WaitOne();

            //decrease connection count
            _connectionCount--;

            if (_connectionCount < 0)
                _connectionCount = 0;

            //if connectin count is zero then disconnect
            if (_connectionCount == 0)
            {
                _connection.Close();
                _connection.Dispose();
            }

            _mutex.ReleaseMutex();
        }

        /// <summary>
        /// Add or update a collection of Manga into database
        /// </summary>
        internal static void SaveManga(ICollection<Manga> mangaCol)
        {
            if (mangaCol.Count > 0)
            {
                int newMangaCount = 0;
                int duplicatedMangaCount = 0;

                //connect to database
                ConnectToDatabase();

                //create command
                foreach (Manga manga in mangaCol)
                {
                    try
                    {
                        String query = "INSERT INTO Manga VALUES(@MangaURL, @MangaName, @MangaSite)";
                        SQLiteCommand cmd = new SQLiteCommand(_connection);
                        cmd.CommandText = query;

                        //add additional information as parameters
                        cmd.Parameters.Add(new SQLiteParameter("@MangaURL", manga.URL));
                        cmd.Parameters.Add(new SQLiteParameter("@MangaName", manga.Name));
                        cmd.Parameters.Add(new SQLiteParameter("@MangaSite", manga.MangaSite.Name));

                        //excute commands
                        cmd.ExecuteNonQuery();
                        newMangaCount++;

                        MGRUtil.WriteLog(manga.MangaSite.Name + ": New Manga saved: " + manga.Name + "(" + manga.URL + ")");
                    }
                    catch
                    {
                        duplicatedMangaCount++;
                    }
                }

                //disconnect from database
                DisconnectFromDatabase();

                //MGRUtil.WriteLog(mangaCol.First<Manga>().MangaSite.Name + ": New Manga saved: " + newMangaCount + ". Duplicated manga: " + duplicatedMangaCount);
            }
        }

        /// <summary>
        /// Add or update a Manga into database
        /// </summary>
        internal static void SaveManga(Manga manga)
        {
            SaveManga(new Manga[] { manga });
        }

        /// <summary>
        /// Retrieve all manga from all registered sites
        /// </summary>
        /// <returns></returns>
        internal static IList<Manga> GetMangaList()
        {
            List<Manga> mangaList = new List<Manga>();

            //connect to database
            ConnectToDatabase();

            String query = "SELECT MangaURL, MangaName, MangaSite FROM Manga ORDER BY MangaName, MangaSite, MangaURL";
            SQLiteCommand cmd = new SQLiteCommand(query, _connection);

            SQLiteDataReader dataReader = cmd.ExecuteReader();

            while (dataReader.Read())
            {
                Manga manga = new Manga();
                manga.URL = dataReader.GetString(0);
                manga.Name = dataReader.GetString(1);
                manga.MangaSite = GetMangaSite(dataReader.GetString(2));

                mangaList.Add(manga);
            }

            dataReader.Close();

            //disconnect from database
            DisconnectFromDatabase();

            return mangaList;
        }

        internal static MangaSite GetMangaSite(string mangaSiteName)
        {
            foreach (MangaSite mangaSite in GetMangaSiteList())
            {
                if (mangaSite.Name.Equals(mangaSiteName))
                    return mangaSite;
            }

            return null;
        }

        /// <summary>
        /// Retrieve the collection of Manga of the given MangaSite
        /// </summary>
        internal static ICollection<Manga> GetMangaList(MangaSite mangaSite)
        {
            List<Manga> mangaList = new List<Manga>();

            //connect to database
            ConnectToDatabase();

            String query = "SELECT MangaURL, MangaName FROM Manga WHERE MangaSite = @MangaSite ORDER BY MangaName, MangaURL";
            SQLiteCommand cmd = new SQLiteCommand(query, _connection);
            cmd.Parameters.Add(new SQLiteParameter("@MangaSite", mangaSite.Name));

            SQLiteDataReader dataReader = cmd.ExecuteReader();

            while (dataReader.Read())
            {
                Manga manga = new Manga();
                manga.URL = dataReader.GetString(0);
                manga.Name = dataReader.GetString(1);
                manga.MangaSite = mangaSite;

                mangaList.Add(manga);
            }

            dataReader.Close();

            //disconnect from database
            DisconnectFromDatabase();

            return mangaList;
        }

        private static MangaSite MangaReader
        {
            get
            {
                //MANGA READER
                MangaSite mangaSite = new MangaSite();

                mangaSite.ChapterNamePattern = ": [^<]*<";
                //: Wings of the Wind 1</td><td>07/29/2009<

                //mangaSite.ChapterOrderPattern = string.Format("{0}</a> :", StringUtil.IntPattern);
                mangaSite.ChapterOrderPattern = string.Format("{0}(?=</a> :)", StringUtil.IntPattern);
                //9</a> :

                mangaSite.ChapterPattern = "chico_manga\"></div>\\s+<a href=\"[^#\"]+\">[^<]+</a> : [^<]*<";
                //chico_manga"></div>{SPACE}<a href="/125-6227-1/vinland-saga/chapter-55.html">Vinland Saga 55</a> : Slave<

                mangaSite.ChapterTotalPagePattern = "</select> of [^<]+<";
                //</select> of 31<

                mangaSite.MangaListURL = @"http://www.mangareader.net/alphabetical";

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>07 Ghost<

                mangaSite.MangaNextPagePattern = String.Empty;

                mangaSite.MangaPattern = string.Format("<li><a href=\"/{0}/[^#.\"]+.html\">[^<]+<", StringUtil.IntPattern);
                //<li><a href="/115/hajime-no-ippo.html">Hajime no Ippo</a></li>

                mangaSite.MatureParam = string.Empty;

                mangaSite.Name = "MangaReader";

                //mangaSite.PageImagePattern = "id=\"img\" src=\"[^#\"]+\"";
                mangaSite.PageImagePattern = string.Format("id=\"img\" width=\"{0}\" height=\"{0}\" src=\"[^\"]+\"", StringUtil.IntPattern);
                //id="img" width="800" height="1143" src="http://i999.mangareader.net/naruto/524/naruto-1769015.jpg"

                mangaSite.PageNextPagePattern = "href=\"[^#\"]+\"><img id=\"img\"";
                //href="/224-16199-2/anima/chapter-41.html"><img id="img" 

                return mangaSite;
            }
        }

        private static MangaSite MangaFox
        {
            get
            {
                //MANGA FOX
                MangaSite mangaSite = new MangaSite();

                mangaSite.ChapterNamePattern = ": [^<]*<";
                //: Afterwords<

                mangaSite.ChapterOrderPattern = string.Format("(Vol.{0} )?Ch.{0}", StringUtil.DoublePattern);
                //Vol.07 Ch.004

                mangaSite.ChapterPattern = "href=\"[^#\"]+\" class=\"chico\">[^<]+</a>\\s+(<s|</td)";
                //href="/manga/trace/v07/c004/" class="chico">Vol.07 Ch.004: Afterwords</a>{space here}</td>
                //href="/manga/fairytale_of_winter/v00/c001/" class="chico"> Fairytale of Winter Vol.00 Ch.001: Oneshot</a><span class="newch">new</span>    

                mangaSite.ChapterTotalPagePattern = string.Format("of {0}\\s+<", StringUtil.IntPattern);
                //of 106{space here}<

                mangaSite.MangaListURL = @"http://www.mangafox.com/directory/all/";

                mangaSite.MangaPattern = "href=\"/manga/[^/#\"]+/\" class=\"manga_(open|close)\">[^<]+<";
                //href="/manga/a_kiss_love_and_a_prince/" class="manga_open/close">A Kiss, Love, and a Prince<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>A Kiss, Love, and a Prince<

                mangaSite.MangaNextPagePattern = "href=\"[^#\"]+\"><span class=\"next\"";
                //href="3.htm"><span class="next"

                mangaSite.MatureParam = "?no_warning=1";

                mangaSite.Name = "MangaFox";

                mangaSite.PageImagePattern = "enlarge\\(\\);\"><img src=\"[^\"]+\"";
                //enlarge();"><img src="http://7.p.s.mfcdn.net/store/manga/6455/01-001.2/compressed/ca_house_in_venice.a_house_in_venice_-_000.jpg"

                mangaSite.PageNextPagePattern = "href=\"[^#\"]+\" onclick=\"return enlarge";
                //href="2.html" onclick="return enlarge

                return mangaSite;
            }
        }

        private static MangaSite Mangable
        {
            get
            {
                //MANGABLE
                MangaSite mangaSite = new MangaSite();
                mangaSite.Name = "Mangable";
                mangaSite.MangaListURL = @"http://mangable.com/manga-list/";

                mangaSite.MatureParam = string.Empty;
                //no mature filtering

                mangaSite.MangaPattern = "href=\"http://mangable.com/[^#\"]+\" title=\"[^\"]+ Manga\"";
                //href="http://mangable.com/futari_ecchi/" title="Futari Ecchi Manga">

                mangaSite.MangaNamePattern = "title=\"[^\"]+ Manga\"";
                //title="Futari Ecchi Manga">

                mangaSite.MangaNextPagePattern = string.Empty;
                //no paging

                mangaSite.ChapterPattern = string.Format("href=\"http://mangable.com/[^#\"]+\" title=\"[^\"]+ Chapter {0}\"", StringUtil.DoublePattern);
                //href="http://mangable.com/gantz/chapter-329/" title="Gantz Chapter 329"

                mangaSite.ChapterNamePattern = string.Empty;
                //no pattern

                mangaSite.ChapterOrderPattern = string.Format("(?<=Chapter ){0}", StringUtil.DoublePattern);
                //Chapter 329

                //mangaSite.ChapterTotalPagePattern = string.Format("Page {0}(-{0})?</option>[^0-9]+</select>", StringUtil.IntPattern);
                mangaSite.ChapterTotalPagePattern = string.Format("Page {0}(-{0})?</option>(?!.*Page {0}(-{0})?<)", StringUtil.IntPattern);
                //mangaSite.ChapterTotalPagePattern = string.Format("Page (c-)?{0}</option>(?!.* (c-)?{0})", StringUtil.IntPattern);
                //Page 16</option>      		</select>                
                //Page 18-19</option><option value="credits">Page credits</option>      		</select>
                //Page 29</option><option value="cover-back">Page cover-back</option><option value="credits">Page credits</option><option value="credits2">Page credits2</option>      		</select>


                mangaSite.PageImagePattern = "src=\"http://mangable.com/files/images/[^#\"]+\" class=\"image";
                //img src="http://mangable.com/files/images/judge/5/46.jpg" class="image

                mangaSite.PageNextPagePattern = "href=\"/[^#\"]+\" title=\"[^\"]+ Chapter [0-9]+\"><img";
                //href="/gantz/chapter-328/2/" title="Gantz Chapter 328"><img

                return mangaSite;
            }
        }

        private static MangaSite MangaToshokan
        {
            get
            {
                //MANGATOSHOKAN
                MangaSite mangaSite = new MangaSite();

                mangaSite.ChapterNamePattern = "<span>: [^<]+<";
                //<span>: Rose (28)<

                mangaSite.ChapterNextPagePattern = "href='http://www.mangatoshokan.com/series/[^']+'>Next &raquo;</a>";
                //<a href='http://www.mangatoshokan.com/series/Noblesse/2'>Next &raquo;</a>

                mangaSite.ChapterOrderPattern = "(?<=Chapter )[^\"]+(?= now)";
                //Chapter v23c1 now

                mangaSite.ChapterPattern = "href='/read/[^']+' title=\"Read [^\"]+\">[^<]+</a><span>[^<]*<";
                //href='/read/Trace/MidnightMoon-Scans/84' title="Read Trace Chapter 84 now!">Trace 84</a><span>: Rose (28)<
                //href='/read/Die/Celestial-Scans/Oneshot' title="Read Die Chapter Oneshot now!">Die Oneshot</a><span><

                mangaSite.ChapterTotalPagePattern = string.Format("</select> of {0}", StringUtil.IntPattern);
                //</select> of 18

                mangaSite.MangaListURL = @"http://www.mangatoshokan.com/read/";

                mangaSite.MangaPattern = "href='/series/[^']+' title='View info for [^']+'>[^<]+<";
                //href='/series/I-Want-You' title='View info for I Want You'>I Want You<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>I Want You<

                mangaSite.MangaNextPagePattern = string.Empty;
                //manga paging not implemented

                mangaSite.MatureParam = string.Empty;
                //no mature filtering

                mangaSite.Name = "MangaToshokan";

                mangaSite.PageImagePattern = "dir='rtl'><img src=\"[^\"]+\"";
                //dir='rtl'><img src="http://m4.mangatoshokan.com/1/12prince/5350/Half_Prince_v01_c002_p074.png"

                mangaSite.PageNextPagePattern = "href=\"/read/[^\"]+\" dir='rtl'";
                //href="/read/Id/A-Team/101/2" dir='rtl'

                return mangaSite;
            }
        }

        private static MangaSite MangaAnimeA
        {
            get
            {
                //MANGA ANIMEA
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "MangaAnimeA";
                mangaSite.MangaListURL = @"http://manga.animea.net/browse.html";

                mangaSite.MangaPattern = "<tr><td><a href=\"/[^/]+.html\" class=\"(in)?complete_manga\" title=\"[^\"]+ manga\"";
                //<tr><td><a href="/16-life.html" class="complete_manga" title="16 Life manga"
                //<tr><td><a href="/16-engaged.html" class="incomplete_manga" title="16 Engaged manga"

                mangaSite.MangaNamePattern = "\"[^\"]+ manga\"";
                //"16 Engaged manga"

                mangaSite.MatureParam = "?skip=1";

                mangaSite.MangaNextPagePattern = "href=\"[^\"]+\">Next";
                //href="?page=1">Next

                mangaSite.ChapterPattern = "href=\"http://manga.animea.net/[^\\.]+-chapter-[^\"]+.html\">[^<]+</a>[^<]*<";
                //href="http://manga.animea.net/berserk-chapter-314.html">Berserk 314</a> Human Tentacles <
                //href="http://manga.animea.net/berserk-chapter-1.html">Berserk 1</a>  <
                //href="http://manga.animea.net/m-chapter-Volume 1 [Complete].html">M Volume 1 [Complete]<
                //href="http://manga.animea.net/umisho-chapter-34-35.html">Umisho 34-35< //TODO

                mangaSite.ChapterNamePattern = "/a>[^<]*<";
                ///a> Human Tentacles <

                mangaSite.ChapterOrderPattern = "(?<=chapter-).+(?=.html)";
                //chapter-314.html

                mangaSite.ChapterStartReadingPattern = "href=\"[^\"]*\">Start reading";
                //href="http://manga.animea.net/berserk-chapter-306-page-1.html">Start reading

                mangaSite.ChapterTotalPagePattern = string.Format("of {0}</title>", StringUtil.IntPattern);
                //of 14</title>

                mangaSite.PageImagePattern = "imagelink\"><img src=\"[^\"]+\"";
                //imagelink"><img src="http://s1-a.animea-server.net/4%2F306_BAVMW%2F%2F01..jpg"

                mangaSite.PageNextPagePattern = "href=\"[^#\"]+\" style";
                //href="http://manga.animea.net/berserk-chapter-306-page-2.html" style

                return mangaSite;
            }
        }

        private static MangaSite MangaVolume
        {
            get
            {
                //MANGA VOLUME
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "MangaVolume";
                mangaSite.MangaListURL = @"http://www.mangavolume.com/manga-archive/mangas";

                mangaSite.MangaPattern = "<td><a href=\"/serie-archive/mangas-[^/]+/\">[^<]+<";
                //<td><a href="/serie-archive/mangas-3-gatsu-no-lion/">3 Gatsu no Lion<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>3 Gatsu no Lion<

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = string.Format("<li><a href=\"/manga-archive/mangas/npage-{0}\" title=\"Next", StringUtil.IntPattern);
                //<li><a href="/manga-archive/mangas/npage-2" title="Next

                mangaSite.ChapterPattern = "<td><a href=\"/[^\"]+/\">[^<]+</a></td>";
                //<td><a href="/all-1/chapter-all-1-3/">All 1 3</a></td>

                mangaSite.ChapterNamePattern = string.Empty; //no name

                mangaSite.ChapterOrderPattern = string.Format("{0}(?=</a)", StringUtil.DoublePattern);
                //3</a

                mangaSite.ChapterNextPagePattern = "href=\"[^\"]+\" title=\"Next";
                //href="/serie-archive/mangas-zetman/npage-4" title="Next

                mangaSite.ChapterStartReadingPattern = string.Empty; //not "start reading" required

                mangaSite.ChapterTotalPagePattern = string.Format("#{0}</option></select>", StringUtil.IntPattern);
                //#033</option></select>

                mangaSite.PageImagePattern = "img src=\"http://[^\"]+\" alt=\"CLICK";
                //img src="http://media2.mangavolume.com/images/manga/normal/6/7/26753_569512.jpg" alt="CLICK

                mangaSite.PageNextPagePattern = "colspan=\"3\" align=\"center\"><a href=\"/[^\"]+\"";
                //colspan="3" align="center"><a href="/3x3-eyes/chapter-3x3-eyes-4/1"

                return mangaSite;
            }
        }

        private static MangaSite ReadHentai
        {
            get
            {
                //MANGA VOLUME
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "ReadHentai";
                mangaSite.MangaListURL = @"http://readhentai.net/fullseries.php";

                mangaSite.MangaPattern = string.Format("href=\"http://readhentai.net/preview.php\\?mangaid={0}\" title=\"[^\"]+\"", StringUtil.IntPattern);
                //href="http://readhentai.net/preview.php?mangaid=1140" title="18 Kaiten Mouth and Ass Toughness"

                mangaSite.MangaNamePattern = "title=\"[^\"]+\"";
                //title="18 Kaiten Mouth and Ass Toughness"

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = string.Empty; //no paging

                mangaSite.ChapterPattern = "href=\"http://readhentai.net/reader.php[^\"]+\"";
                //href="http://readhentai.net/reader.php?mangaid=251&pagenum=1"

                mangaSite.ChapterNamePattern = string.Empty; //no name -> use string.Empty

                mangaSite.ChapterOrderPattern = string.Empty; //no number -> use auto increasing number

                mangaSite.ChapterStartReadingPattern = string.Empty; //no "start reading" required

                mangaSite.ChapterTotalPagePattern = string.Format("of {0}\\)", StringUtil.IntPattern);
                //of 20)

                mangaSite.PageImagePattern = "href=\"http://(cache|image).readhentai.net/manga/[^\"]+\"";
                //href="http://image.readhentai.net/manga/24 Hour Rehabilitation Ward-1248587774/24 Hour Rehabilitation Ward/149.jpg"
                //http://cache.readhentai.net/manga/%5BTakeda%20Hiromitsu%5D%20Kanokon%20-%20Kontama%20Plus%20%5BEng%5D-1289893658/%5BTakeda%20Hiromitsu%5D%20Kanokon%20-%20Kontama%20Plus%20%5BEng%5D/01.jpg

                mangaSite.PageNextPagePattern = "href=\"/reader.php\\?mangaid=[^\"]+\">Next";
                //href="/reader.php?mangaid=251&pagenum=2">Next

                return mangaSite;
            }
        }

        private static MangaSite MangaPark
        {
            get
            {
                //MANGA VOLUME
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "MangaPark";
                mangaSite.MangaListURL = @"http://www.mangapark.com/list.html";

                mangaSite.MangaPattern = "href=\"/manga/[^\"]+\" class=\"ico\">[^<]+<";
                //href="/manga/18-Diary.html" class="ico">18 Diary<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>18 Diary<

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = "href=\"/list/all/[^\"]+\" target=\"_self\">Next";
                //href="/list/all/2.html" target="_self">Next

                //mangaSite.ChapterPattern = string.Format("href=\"/manga/[^\"]+\" title=\"[^>]+ Ch\\.{0} [^\"]*\"", StringUtil.DoublePattern);
                mangaSite.ChapterPattern = "href=\"/manga/[^\"]+\" title=\"[^>]+:[^\"]*\">";
                //href="/manga/Berserk/54.html" title="Berserk Ch.318 Bestial Warrior : Bestial Warrior"
                //href="/manga/M--KATSURA-Masakazu-/1.html" title="M (KATSURA Masakazu) Vol.1   : "

                mangaSite.ChapterNamePattern = string.Empty; //no name pattern

                mangaSite.ChapterOrderPattern = string.Format("(Vol.{0} Ch.{0}|Vol.{0}|Ch.{0})(?=\\s+:)", "[^:]+");
                //Ch.318 

                mangaSite.ChapterStartReadingPattern = string.Empty; //no "start reading" required

                mangaSite.ChapterTotalPagePattern = string.Format("/{0}<", StringUtil.IntPattern);
                ///219<

                mangaSite.PageImagePattern = "manga_pic_1\"\\s+src=\"[^\"]+\"";
                //manga_pic_1" {SPACE} src="http://pic.mangapark.com/manga/123/48793/2.jpg" 

                mangaSite.PageNextPagePattern = "href=\"/manga/[^\"]+\" target=\"_self\">Next";
                //href="/manga/Bousou-Shojo/1/5.html" target="_self">Next

                return mangaSite;
            }
        }

        private static MangaSite CityManga
        {
            get
            {
                //CITY MANGA
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "CityManga";
                mangaSite.MangaListURL = @"http://www.citymanga.com/manga-list/";

                mangaSite.MangaPattern = "\"coll1\"><a href=\"/[^\"]+\">[^<]+<";
                //"coll1"><a href="/great_mazinger/">Great Mazinger<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>Great Mazinger<

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = string.Empty; //no paging

                mangaSite.ChapterPattern = string.Format("\"coll1\"><a href=\"http://www.citymanga.com/[^\"]+\" title=\"[^>]+ Chapter {0}\">", StringUtil.DoublePattern);
                //"coll1"><a href="http://www.citymanga.com/hajime_no_ippo/chapter-905/" title="Hajime no Ippo Chapter 905">

                mangaSite.ChapterNamePattern = string.Empty; //no pattern

                mangaSite.ChapterOrderPattern = string.Format("(?<=Chapter ){0}", StringUtil.DoublePattern);
                //Chapter 905

                mangaSite.ChapterStartReadingPattern = string.Empty; //no "start reading" required

                mangaSite.ChapterTotalPagePattern = string.Format("Page (c-)?{0}</option>(?!.* (c-)?{0})", StringUtil.IntPattern);
                //Page 27</option><option value="credits+rant">Page credits+rant</option>      		</select>

                mangaSite.PageImagePattern = "src=\"/files/images/[^\"]+\" class=\"image";
                //"/files/images/hajime_no_ippo/913/1.jpg" class="image

                mangaSite.PageNextPagePattern = "href=\"[^\"]+\" title=\"[^\"]+\"><img";
                //href="/hajime_no_ippo/chapter-913/2/" title="Hajime no Ippo Chapter 913"><img

                return mangaSite;
            }
        }

        private static MangaSite MangaRush
        {
            get
            {
                //MANGA RUSH
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "MangaRush";
                mangaSite.MangaListURL = @"http://www.mangarush.com/mangas";

                mangaSite.MangaPattern = "<tr>\\s+<td class=\"mangalist\">\\s+<a href=\"http://www.mangarush.com/manga/[^\"]+\" title=\"[^>]+\">[^<]+</a>";
                //<tr>{SPACE}<td class="mangalist">{SPACE}<a href="http://www.mangarush.com/manga/6mm-no-taboo" title="-6mm no Taboo">-6mm no Taboo</a>

                mangaSite.MangaNamePattern = ">[^<]+</a>";
                //>-6mm no Taboo</a>

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = "\"current\">[^<]+</a>\\s+<a href=\"[^\"]+\"";
                //class="current">1</a>{SPACE}<a href="http://www.mangarush.com/mangas/p-2"

                mangaSite.MangaPageFormat = "http://www.mangarush.com/mangas/p-{0}";
                //http://www.mangarush.com/mangas/p-2

                mangaSite.MangaLastPageNumberPattern = string.Format("pagination\">\\s+<strong>{0}<", StringUtil.IntPattern);
                //pagination">{SPACE}<strong>265<

                //mangaSite.ChapterPattern = string.Format("href=\"[^\"]+\" class=\"chapters\">[^<]+ Ch. {0}[^<]*<", StringUtil.DoublePattern); //REMOVE LATER
                mangaSite.ChapterPattern = "href=\"[^\"]+\" class=\"chapters\">[^<]+<";
                //href="http://www.mangarush.com/manga/aiki/57" class="chapters">AIKI Ch. 57: Like A Sword<

                mangaSite.ChapterNamePattern = ": [^<]+<";
                //: Like A Sword<

                mangaSite.ChapterOrderPattern = string.Format("(Vol. {0} )?Ch. {0}", StringUtil.DoublePattern);
                //Ch. 57

                mangaSite.ChapterStartReadingPattern = "href=\"http://www.mangarush.com/manga/[^\"]+\">Begin reading";
                //href="http://www.mangarush.com/manga/aiki/57/p-1">Begin reading

                mangaSite.ChapterTotalPagePattern = string.Format(">{0}</option>\\s+</select>", StringUtil.IntPattern);
                //>25</option>{SPACE}</select>

                mangaSite.PageImagePattern = "src=\"http://www.mangarush.com/files/mangas/[^\"]+\" alt";
                //src="http://www.mangarush.com/files/mangas/aiki/57/1.jpg" alt

                mangaSite.PageNextPagePattern = "href=\"http://www.mangarush.com/manga/[^\"]+\"><img";
                //href="http://www.mangarush.com/manga/aiki/57/p-2"><img

                return mangaSite;
            }
        }

        private static MangaSite DoujinToshokan
        {
            get
            {
                //DOUJIN TOSHOKAN
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "DoujinToshokan";
                mangaSite.MangaListURL = @"http://www.doujintoshokan.com/read?filter=3";

                mangaSite.MangaPattern = "href='/series/[^']+' title='View Info Page for [^']+'";
                //href='/series/A-Dream-For-Two' title='View Info Page for A Dream For Two'

                mangaSite.MangaNamePattern = "View Info Page for [^']+'";
                //View Info Page for A Dream For Two'

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = string.Empty; //no paging

                mangaSite.ChapterPattern = string.Format("href='/read/[^']+' title=\"Read [^>]+\">[^<]+</a><span>[^<]*<", StringUtil.DoublePattern);
                //href='/read/Stop-BIG-SISTER/Lhytiss/0' title="Read Stop! BIG SISTER Chapter 0 now!">Stop! BIG SISTER 0</a><span>: Contents<
                //href='/read/Stop-BIG-SISTER/Lhytiss/3' title="Read Stop! BIG SISTER Chapter 3 now!">Stop! BIG SISTER 3</a><span><
                //href='/read/Missing-Each-Other-Ensemble/HayamaKotono/8' title="Read "Missing Each Other" Ensemble Chapter 8 now!">"Missing Each Other" Ensemble 8</a><span>: Sweet Sweet Date<

                mangaSite.ChapterNamePattern = ": [^<]+<";
                //: Contents<

                mangaSite.ChapterOrderPattern = string.Format(" {0}</a>", StringUtil.DoublePattern);
                // 0</a>

                mangaSite.ChapterStartReadingPattern = string.Empty; //no start reading link

                mangaSite.ChapterTotalPagePattern = string.Format("select> of {0}<", StringUtil.IntPattern);
                //select> of 12<

                mangaSite.PageImagePattern = "(rpage|rtl)'><img src=\"http://[^\"]+\"";
                //rtl'><img src="http://m6.doujintoshokan.com/s/stopbigsister/5888/Yamete_Onee_chan_001.jpg"
                //rpage'><img src="http://m6.doujintoshokan.com/s/stopbigsister/5896/Yamete_Onee_chan_211.jpg
                //rpage'><a href="/read/Stop-BIG-SISTER/Lhytiss/8/17" dir='rtl'><img src="http://m6.doujintoshokan.com/s/stopbigsister/5896/Yamete_Onee_chan_208.jpg"

                mangaSite.PageNextPagePattern = "href=\"/read/[^\"]+\">Next &raquo;";
                //href="/read/Stop-BIG-SISTER/Lhytiss/0/2">Next &raquo;

                return mangaSite;
            }
        }

        private static MangaSite MangaHere
        {
            get
            {
                //MANGA HERE
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "MangaHere";
                mangaSite.MangaListURL = @"http://www.mangahere.com/directory/";

                mangaSite.MangaPattern = "<div class=\"manga_text\">\\s+<h4><a href=\"/manga/[^\"]+\" title=\"[^\"]+\"";
                //<div class="text">{SPACE}<a href="http://www.mangahere.com/manga/naruto/" >{SPACE}Naruto<
                //<div class="manga_text">{SPACE}<h4><a href="/manga/one_piece/" title="One Piece"

                mangaSite.MangaNamePattern = "title=\"[^\"]+\"";
                //title="One Piece"

                mangaSite.MatureParam = "?no_warning=1";

                mangaSite.MangaNextPagePattern = "href=\"[^\"]+\" class=\"next";
                //href="2.htm" class="next

                mangaSite.MangaPageFormat = "http://www.mangahere.com/directory/{0}.htm";
                //http://www.mangahere.com/directory/1.htm

                mangaSite.MangaLastPageNumberPattern = string.Format("{0}</a><a href=\"[^\"]+\" class=\"next", StringUtil.IntPattern);
                //href="228.htm">228</a><a href="2.htm" class="next

                mangaSite.ChapterPattern = string.Format("<div class=\"l1\">\\s+<a href=\"[^\"]+\">\\s+[^<]+\\s+</a>\\s+<span>[^<]*</span>\\s+<span>[^<]*<", StringUtil.DoublePattern);
                //<div class="l1">{SPACE}<a href="/manga/katekyo_hitman_reborn/v31/c319/">{SPACE}Katekyo Hitman Reborn 319{SPACE}</a>{SPACE}<span>Vol.31 </span>{SPACE}<span>Dark Shadow<

                mangaSite.ChapterNamePattern = ">[^<]*<$";
                //>Dark Shadow<

                mangaSite.ChapterOrderPattern = string.Format("{0}(?=\\s+<)", StringUtil.DoublePattern);
                //319{SPACE}<

                mangaSite.ChapterStartReadingPattern = string.Empty; //None

                mangaSite.ChapterTotalPagePattern = string.Format(">{0}</option>\\s+</select>", StringUtil.IntPattern);
                //>17</option>{SPACE}</select>

                mangaSite.PageImagePattern = "enlarge\\(\\);\"><img src=\"[^\"]+\"";
                //enlarge();"><img src="http://4.p.s.mhcdn.net/store/manga/880/22-200.0/compressed/01.jpg"

                mangaSite.PageNextPagePattern = "href=\"[^\"]+\" class=\"button-page\"><span>Next";
                //href="http://www.mangahere.com/manga/katekyo_hitman_reborn/v22/c200/2.html" class="button-page"><span>Next

                return mangaSite;
            }
        }

        private static MangaSite ZenManga
        {
            get
            {
                MangaSite mangaSite = new MangaSite();

                mangaSite.Name = "ZenManga";
                mangaSite.MangaListURL = @"http://www.zenmanga.com/mangas/index/page:1/limit:45";

                mangaSite.MangaPattern = "<div class=\"MangaInfo\">\\s+<strong><a href=\"/mangas/title/[^\"]+\">[^<]+</a>";
                //<div class="MangaInfo">{SPACE}<strong><a href="/mangas/title/Oboretai">Oboretai</a>

                mangaSite.MangaNamePattern = ">[^\"]+</a>";
                //>Oboretai</a>

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = "href=\"[^\"]+\">Next<";
                //href="/mangas/index/page:3/limit:45">Next<

                mangaSite.MangaPageFormat = "http://www.zenmanga.com/mangas/index/page:{0}/limit:45";
                //http://www.zenmanga.com/mangas/index/page:2/limit:45

                mangaSite.MangaLastPageNumberPattern = string.Format("{0}</a></span><a href=\"[^\"]+\">Next", StringUtil.IntPattern);
                //4</a></span><a href="/mangas/index/page:3/limit:45">Next

                mangaSite.ChapterPattern = "class=\"chapterNo\">\\s+<a href=\"/mangas/view/[^\"]+\"";
                //class="chapterNo">{SPACE}<a href="/mangas/view/Endless Eden#Endless_Eden_001"

                mangaSite.ChapterNamePattern = string.Empty; //no name pattern

                mangaSite.ChapterOrderPattern = string.Format("{0}(?=\")", StringUtil.DoublePattern);
                //001"

                mangaSite.ChapterStartReadingPattern = string.Empty; //None

                mangaSite.ChapterTotalPagePattern = string.Empty;
                //GRRRRRRRRRRRRRRRRRRRRRRRR

                mangaSite.PageImagePattern = string.Empty;
                //GRRRRRRRRRRRRRRRRRRRRRRRR

                mangaSite.PageNextPagePattern = string.Empty;
                //GRRRRRRRRRRRRRRRRRRRRRRRR

                return mangaSite;
            }
        }

        private static MangaSite MangaEden
        {
            get
            {
                MangaSite mangaSite = new MangaEden();

                mangaSite.Name = "MangaEden";
                mangaSite.MangaListURL = @"http://static2.mangaeden.com/data.js";

                mangaSite.MangaPattern = "href=\"/En/[^/]+/\">[^<]+<";
                //href="/En/SPY/">SPY<href="/En/SPY/">SPY<

                mangaSite.MangaNamePattern = ">[^<]+<";
                //>SPY<

                mangaSite.MatureParam = string.Empty; //no filter

                mangaSite.MangaNextPagePattern = string.Empty; //no paging

                mangaSite.MangaPageFormat = string.Empty;

                mangaSite.MangaLastPageNumberPattern = string.Empty;

                mangaSite.ChapterPattern = string.Format("[\"{0}\", '<a href=\"/En/[^\"]+\">[^<]+<", StringUtil.DoublePattern);
                //["331", '<a href="/En/Gantz/331/">Gantz 331 \u002D Reverse Invasion<

                mangaSite.ChapterNamePattern = "\u002D [^<]+<";
                //\u002D Reverse Invasion<

                mangaSite.ChapterOrderPattern = string.Format("(?<=\\[\"){0}(?=\")", StringUtil.DoublePattern);
                //["331"

                mangaSite.ChapterStartReadingPattern = string.Empty; //None

                mangaSite.ChapterTotalPagePattern = string.Format("> of {0}<", StringUtil.IntPattern);
                //> of 36<

                mangaSite.PageImagePattern = "rel=\"image_src\" href=\"[^\"]+\"";
                //rel="image_src" href="http://static2.mangaeden.com/mangasimg/b6/b690a50cc69cc1ac6a75dbf56624d469dab513ebec9b5779d928c773.png"

                mangaSite.PageNextPagePattern = "href=\"[^\"]+\" alt=\"Next Page\"";
                //href="/En/+Inuyasha/558/2/" alt="Next Page"

                return mangaSite;
            }
        }

        /// <summary>
        /// Retrieve a collection of all registered MangaSites
        /// </summary>
        internal static ICollection<MangaSite> GetMangaSiteList()
        {
            if (_mangaSiteList == null)
            {
                _mangaSiteList = new List<MangaSite>();

                //MangaSiteAll mangaSiteAll = new MangaSiteAll();
                //mangaSiteAll.Name = "ALL";

                _mangaSiteList.Add(MangaReader);
                _mangaSiteList.Add(MangaEden);
                _mangaSiteList.Add(CityManga);
                _mangaSiteList.Add(Mangable);
                //_mangaSiteList.Add(MangaRush);
                //_mangaSiteList.Add(MangaToshokan);
                //_mangaSiteList.Add(ZenManga);
                //_mangaSiteList.Add(MangaHere);
                //_mangaSiteList.Add(MangaPark);
                //_mangaSiteList.Add(MangaVolume);
                //_mangaSiteList.Add(MangaFox);
                //_mangaSiteList.Add(MangaAnimeA);
                //_mangaSiteList.Add(mangaSiteAll);

                //_mangaSiteList.Add(DoujinToshokan);
                //_mangaSiteList.Add(ReadHentai);
            }

            return _mangaSiteList;
        }

        internal static Manga GetMangaByURL(string mangaURL)
        {
            Manga manga = null;

            //connect to database
            ConnectToDatabase();

            String query = "SELECT MangaURL, MangaName, MangaSite FROM Manga WHERE MangaURL = '" + mangaURL + "'";
            SQLiteCommand cmd = new SQLiteCommand(query, _connection);

            SQLiteDataReader dataReader = cmd.ExecuteReader();

            if (dataReader.Read())
            {
                manga = new Manga();
                manga.URL = dataReader.GetString(0);
                manga.Name = dataReader.GetString(1);
                manga.MangaSite = GetMangaSite(dataReader.GetString(2));
            }
            else
            {
                manga = null;
            }

            dataReader.Close();

            //disconnect from database
            DisconnectFromDatabase();

            return manga;
        }
    }
}
